#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include "mysem.h"

typedef struct {
    int value;
    pthread_mutex_t mut;
    pthread_cond_t cond;
}mysem_st;

mysem_t *mysem_init(int initval)
{
    if(initval <= 0){
        return NULL;
    }

    mysem_st *me = malloc(sizeof(mysem_st));
    if(!me){
        fprintf(stderr, "malloc() failed\n");
        return NULL;
    }

    me->value = initval;
    pthread_mutex_init(&me->mut, NULL);
    pthread_cond_init(&me->cond, NULL);

    return me;
}

int mysem_add(mysem_t *ptr, int n)
{
    mysem_st *me = ptr;

    if(n <= 0 || n > me->value){
        //不能返回 return -EINVAL;
    }

    pthread_mutex_lock(&me->mut);
    me->value += n;
    //printf("myseb_add %d\n", me->value);
    pthread_cond_broadcast(&me->cond);
    pthread_mutex_unlock(&me->mut);
    return n;
}

int mysem_sub(mysem_t *ptr, int n)
{
    mysem_st *me = ptr;

    if(n <= 0 || n > me->value){
        //不能返回
    }

    pthread_mutex_lock(&me->mut);
    while(me->value < n){
        pthread_cond_wait(&me->cond, &me->mut);
    }
    me->value -= n;
    //printf("myseb_subed %d\n", me->value);
    pthread_mutex_unlock(&me->mut);
    return n;
}

int mysem_destroy(mysem_t *ptr)
{
    mysem_st *me = ptr;
    if(!me){
        return -EINVAL;
    }

    pthread_mutex_destroy(&me->mut);
    pthread_cond_destroy(&me->cond);
    free(me);
    return 0;
}
